package com.ibp.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.pagehelper.StringUtil;
import com.ibp.dao.IbpEventLogDataMapper;
import com.ibp.entity.IbpEventLogData;
import com.ibp.service.StatisticalAnalysisService;

@Service("statisticalAnalysisServiceImpl")
public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisService {
   
	Logger logger = LoggerFactory.getLogger(StatisticalAnalysisServiceImpl.class);
	SimpleDateFormat sf =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	@Autowired
	IbpEventLogDataMapper ibpEventLogDataMapper;
	
	/***
	 * 获取折线图数据
	 * 
	 */
	@Override
	public Map<String,Object> getData(IbpEventLogData elog) {
		long startTime = System.currentTimeMillis();
		//将过滤条件处理成sql语句Like参数
		if(StringUtil.isNotEmpty(elog.getTradeCode())){
			String tradeCode = elog.getTradeCode();
			elog.setTradeCode(tradeCode.replaceAll("\\*", "%").replaceAll("\\?", "_"));
		}
		if(StringUtil.isNotEmpty(elog.getDifferTradeCode())){
			String DifferTradeCode = elog.getDifferTradeCode();
			elog.setTradeCode(DifferTradeCode.replaceAll("\\*", "%").replaceAll("\\?", "_"));
		}
		
		Map<String,Object> map = new HashMap<String,Object>();
		Map<String,Object> map1 = getLineData(elog);
		Map<String,Object> map2 = getPieData(elog);
		
		map.putAll(map1);
		map.putAll(map2);
		
		long consumeTime = System.currentTimeMillis() - startTime;
		logger.info("图表加载总耗时："+ consumeTime +"ms");
		
		return map ;
	}
	
	/***
	 * 获取线性图的数据
	 * 
	 */
	@Override
	public Map<String,Object> getLineData(IbpEventLogData elog) {
		long startTime = System.currentTimeMillis();
		Map<String,Object> map = new HashMap<String,Object>();
		//折线图数据
		Map<String,Object> echarts1 = getTradeCountData(elog);
		map.put("echarts1", echarts1);
		//面积图
		Map<String,Object> echarts3 = getTradeConsumeTime(elog);
		map.put("echarts3", echarts3);
		long consumeTime = System.currentTimeMillis() - startTime;
		logger.info("2个曲线图表加载耗时："+ consumeTime +"ms");
		return map ;
	}

    /****
     * 获取饼图数据
     * 
     */
	@Override
	public Map<String,Object> getPieData(IbpEventLogData elog) {
		long startTime = System.currentTimeMillis();
		Map<String,Object> map = new HashMap<String,Object>();
		//饼图
		Map<String,Object> echarts2 = getTradeCountRate(elog);
		map.put("echarts2", echarts2);
		//饼图
		Map<String,Object> echarts4 = getTradeConsumeTimeRate(elog);
		map.put("echarts4", echarts4);
		long consumeTime = System.currentTimeMillis() - startTime;
		logger.info("2个饼图表加载耗时："+ consumeTime +"ms");
		return map ;
	}

	/***
	 * 
	 * 时间段内，统计每个时间点的交易量 
	 * 
	 */
	@Override
	public Map<String,Object> getTradeCountData(IbpEventLogData elog) {
		Map<String,Object> map = new HashMap<String,Object>();
		//x轴集合
		List<Map<String,Object>> xAxis = new ArrayList<Map<String,Object>>();
		//数据集合
		List<Map<String,Object>> series = new ArrayList<Map<String,Object>>();
		//汇总后的数据 
		List<IbpEventLogData> list = new ArrayList<IbpEventLogData>();
		//x轴对象
		Map<String,Object> xAxis1 = new HashMap<String,Object>();
		//根据时间差计算出x轴数据
		Date startTime = null ;
		Date endTime = null;
		try {
			startTime = sf.parse(elog.getStartTime());
			endTime = sf.parse(elog.getEndTime());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		xAxis1 =  initXAxisData(startTime,endTime,elog.getTradeCountType());
		//统计类型
		String countType = (String) xAxis1.get("count_type");
		xAxis1.put("name", "时间("+ countType +")");
		//x轴数据
		List<String> xData = (List<String>) xAxis1.get("data");
		
		//折线对象
		Map<String,Object> series1 = new HashMap<String,Object>();
		series1.put("name", "交易数");
		//曲线数据
		List<Integer> sData = new ArrayList<Integer>();
       	//按统计类型统计
        list = ibpEventLogDataMapper.getTradeCountDataByCountType(elog);
        //根据x轴数据和统计数据生成曲线数据
		sData = initSeriesData(xData,list);

		series1.put("data", sData);
		
		xAxis.add(xAxis1);
		series.add(series1);

		map.put("xAxis", xAxis);
		map.put("series", series);
		
		return map;
	}

	/***
	 * 
	 * 时间段内，统计每个交易码出现总数的比例分布 
	 * 
	 */
	@Override
	public Map<String,Object> getTradeCountRate(IbpEventLogData elog) {
		Map<String,Object> map = new HashMap<String,Object>();
		//数据集合
		List<Map<String,Object>> series = new ArrayList<Map<String,Object>>();
		//统计数据
		List<IbpEventLogData> list = ibpEventLogDataMapper.getTradeCountRate(elog);
		//series对象
		Map<String,Object> series1 = new HashMap<String,Object>();
		series1.put("name", "交易码");
		//series数据
		List<Map<String,Object>> sData = new ArrayList<Map<String,Object>>();
		for(IbpEventLogData logdata:list){
			Map<String,Object> m = new HashMap<String,Object>();
			m.put("name", logdata.getTradeDescribe());
			m.put("value", logdata.getTradeAmount());
			sData.add(m);
		}
		series1.put("data",sData);
		series.add(series1);
		map.put("series", series);
		return map;
	}

	
	/***
	 * 
	 * 时间段内，统计每个时间点交易保持耗时、通讯接收耗时、应用处理耗时、通讯发送耗时各自平均耗时
	 * 
	 */
	@Override
	public Map<String,Object> getTradeConsumeTime(IbpEventLogData elog) {
		Map<String,Object> map = new HashMap<String,Object>();
		//x轴集合
		List<Map<String,Object>> xAxis = new ArrayList<Map<String,Object>>();
		//数据集合
		List<Map<String,Object>> series = new ArrayList<Map<String,Object>>();
		//统计数据
		List<IbpEventLogData> list = new ArrayList<IbpEventLogData>();
		//legend
		List<String> legendData = Arrays.asList("交易保持耗时","通讯接收耗时","应用处理耗时","通讯发送耗时");
		//x轴对象
		Map<String,Object> xAxis1 = new HashMap<String,Object>();
		//根据时间差计算出x轴数据
		Date startTime = null ;
		Date endTime = null;
		try {
			startTime = sf.parse(elog.getStartTime());
			endTime = sf.parse(elog.getEndTime());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
		xAxis1 =  initXAxisData(startTime,endTime,elog.getTradeCountType());
		//统计类型
		String countType = (String) xAxis1.get("count_type");
		xAxis1.put("name", "时间("+ countType +")");
		//x轴数据
		List<String> xData = (List<String>) xAxis1.get("data");
		
		//折线对象
		Map<String,Object> seriesTradeKeepTime = new HashMap<String,Object>();
		seriesTradeKeepTime.put("name", "交易保持耗时");
		
		Map<String,Object> seriesCommunicateReceiveTime = new HashMap<String,Object>();
		seriesCommunicateReceiveTime.put("name", "通讯接收耗时");
		
		Map<String,Object> seriesAppcationProcessTime = new HashMap<String,Object>();
		seriesAppcationProcessTime.put("name", "应用处理耗时");
		
		Map<String,Object> seriesCommunicateSendTime = new HashMap<String,Object>();
		seriesCommunicateSendTime.put("name", "通讯发送耗时");
		//曲线数据
		List<BigDecimal> tradeKeepTimeData = new ArrayList<BigDecimal>();
		List<BigDecimal> communicateReceiveTimeData = new ArrayList<BigDecimal>();
		List<BigDecimal> appcationProcessTimeData = new ArrayList<BigDecimal>();
		List<BigDecimal> communicateSendTimeData = new ArrayList<BigDecimal>();

		//按统计类型统计
    	list = ibpEventLogDataMapper.getTradeConsumeTimeByCountType(elog);
		//遍历x轴数据，设置series数据
		IbpEventLogData idata =  null;
		for(String ele:xData){
			boolean flag = false ;
			//根据x轴匹配数据
			for(IbpEventLogData ibp:list){
				if(ibp == null) continue ;
				if(ele.equals(ibp.getTimeString())){
					flag = true ;
					idata = ibp ;
					break;
				}
			}
			if(flag){
				tradeKeepTimeData.add(idata.getTradeKeepTime());
				communicateReceiveTimeData.add(idata.getCommunicateReceiveTime());
				appcationProcessTimeData.add(idata.getAppcationProcessTime());
				communicateSendTimeData.add(idata.getCommunicateSendTime());
				idata =  null;
			}else{
				tradeKeepTimeData.add(BigDecimal.valueOf(0));
				communicateReceiveTimeData.add(BigDecimal.valueOf(0));
				appcationProcessTimeData.add(BigDecimal.valueOf(0));
				communicateSendTimeData.add(BigDecimal.valueOf(0));
			}
		}
		seriesTradeKeepTime.put("data", tradeKeepTimeData);
		seriesCommunicateReceiveTime.put("data", communicateReceiveTimeData);
		seriesAppcationProcessTime.put("data", appcationProcessTimeData);
		seriesCommunicateSendTime.put("data", communicateSendTimeData);
		
		//处理x轴和，曲线数据
		xAxis.add(xAxis1);
		series.add(seriesCommunicateSendTime);
		series.add(seriesAppcationProcessTime);
		series.add(seriesCommunicateReceiveTime);
		series.add(seriesTradeKeepTime);

		map.put("legendData", legendData);
		map.put("xAxis", xAxis);
		map.put("series", series);
		return map ;
	}
	
	
	/****
	 * 
	 * 时间段内，统计每个交易码的 交易总耗时 的比例分布
	 * 
	 */
	@Override
	public Map<String,Object> getTradeConsumeTimeRate(IbpEventLogData elog) {
		Map<String,Object> map = new HashMap<String,Object>();
		//数据集合
		List<Map<String,Object>> series = new ArrayList<Map<String,Object>>();
		//统计数据
		List<IbpEventLogData> list = ibpEventLogDataMapper.getTradeConsumeTimeRate(elog);
		//series对象
		Map<String,Object> series1 = new HashMap<String,Object>();
		series1.put("name", "交易码");
		//series数据
		List<Map<String,Object>> sData = new ArrayList<Map<String,Object>>();
		for(IbpEventLogData logdata:list){
			Map<String,Object> m = new HashMap<String,Object>();
			m.put("name", logdata.getTradeDescribe());
			m.put("value", logdata.getTradeTotalTime());
			sData.add(m);
		}
		series1.put("data",sData);
		series.add(series1);
		map.put("series", series);
		return map;
	}			
	
	/****
	 * 按开始时间和结束时间差设置x轴
	 * @param startDate
	 * @param endData
	 */
	private Map<String,Object> initXAxisData(Date startDate,Date endDate,String TradeCountType){
		Map<String,Object> map = new HashMap<String,Object>();
		List<String>  xAxisData  = new ArrayList<String>();
		long startTime = startDate.getTime() ;
		long interval_second = (endDate.getTime() - startDate.getTime())/1000 ;
		//按秒统计
		if("S".equals(TradeCountType)){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			for(int i=0;i<= interval_second;i++){
				long initTime = (long)startTime+i*1000L;
				Date time = new Date(initTime);
				xAxisData.add(sdf.format(time));
			}
			map.put("count_type", "S"); //每秒统计
			map.put("data", xAxisData);
		//每10秒统计	
		}else if("10S".equals(TradeCountType)){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			for(int i=0;i<= interval_second/10;i++){
				long initTime = (long)startTime+i*1000L*10L ;
				Date time = new Date(initTime);
				xAxisData.add(new StringBuilder(sdf.format(time)).replace(18, 19, "0").toString());
			}
			map.put("count_type", "10S"); //每秒统计
			map.put("data", xAxisData);
		//按分钟统计	
		}else if("M".equals(TradeCountType)){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			for(int i=0;i<=(interval_second/60);i++){
				long initTime = (long)startTime+i*1000L*60L ;
				Date time = new Date(initTime);
				xAxisData.add(new StringBuilder(sdf.format(time)).replace(17, 19, "00").toString());
			}
			map.put("count_type", "M"); //每分统计
			map.put("data", xAxisData);
		//每10分钟统计	
		}else if("10M".equals(TradeCountType)){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			for(int i=0;i<=(interval_second/(60*10));i++){
				long initTime = (long)startTime+i*1000L*60L*10L ;
				Date time = new Date(initTime);
				xAxisData.add(new StringBuilder(sdf.format(time)).replace(15, 19, "0:00").toString());
			}
			map.put("count_type", "10M"); //每分统计
			map.put("data", xAxisData);
		//小时统计	
		}else if("H".equals(TradeCountType)){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			for(int i=0;i<=(interval_second/(60*60));i++){
				long initTime = (long)startTime+i*1000L*60L*60L ;
				Date time = new Date(initTime);
				xAxisData.add(new StringBuilder(sdf.format(time)).replace(14, 19, "00:00").toString());
			}
			map.put("count_type", "H"); //每分统计
			map.put("data", xAxisData);
		//天统计	
		}else{
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			for(int i=0;i<=(interval_second/(60*60*24));i++){
				long initTime = (long)startTime+i*1000L*60L*60L*24L ;
				Date time = new Date(initTime);
				xAxisData.add(new StringBuilder(sdf.format(time)).replace(11, 19, "00:00:00").toString());
			}
			map.put("count_type", "D"); //每10分统计
			map.put("data", xAxisData);
		}
		return map;
		
	}
	
	/****
	 * 根据xAxis设置SeriesData
	 * @param xAxis
	 * @param list
	 */
	private List<Integer> initSeriesData(List<String> xAxisData,List<IbpEventLogData> list){
		List<Integer> seriesData = new ArrayList<Integer>() ;
		//遍历x轴数据
		for(String ele : xAxisData){
			int amount = 0 ;
			//根据x轴匹配数据
			for(IbpEventLogData ibp:list){
				if(ibp == null) continue ;
				if(ele.equals(ibp.getTimeString())){
					amount = ibp.getTradeAmount() ;
					break;
				}
			}
			seriesData.add(amount);
			if(amount != 0){
				amount=0; 
			}
		}
		return seriesData ;
	}
	
	
}
